﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Xml;
using Kevin.Comm.Logger;
using Kevin.Shop.Business.Service.Entity.Helper;
using Kevin.Shop.Business.Service.Entity.SalesManagement.Order;
using Kevin.Shop.Integration.PaymentInterface.AlipayMobile;
using RiderShop.Mobile.Common.Component;
using RiderShop.Mobile.Modle.Purchase;
using Kevin.Shop.Business.Core.Configuration;
using Kevin.Shop.Business.SalesManagement.Components.Order;
using Kevin.Shop.Business.Core.Components;
using System.Security.Cryptography;
using System.IO;


namespace RiderShop.WebSite.Controllers.Purchase
{
    public partial class PurchaseController : ThemeController
    {

        #region 字段
        private string _sign_type = ConfigurationManager.AppSettings["Sign_Type"];
        //合作者身份ID
        private string _partner = ConfigurationManager.AppSettings["AlipayPartner"];
        //交易安全检验码，由数字和字母组成的32位字符串
        private string _key = ConfigurationManager.AppSettings["AlipayKey"];
        //RSA 公钥
        private string _RSA_public_key = ConfigurationManager.AppSettings["AlipayRSAPublicKey"];
        //字符编码格式
        private string _input_charset = "utf-8";
        //签约支付宝账号或卖家支付宝帐户
        private string _seller_email = ConfigurationManager.AppSettings["AlipaySeller_email"];
        //页面跳转同步返回页面文件路径
        private string _return_url = ConfigurationManager.AppSettings["Callback_Url"];
        //服务器通知的页面文件路径
        private string _notify_url = ConfigurationManager.AppSettings["Notify_Url"];
        //支付宝网关地址（新）
        private string GATEWAY_NEW = "https://mapi.alipay.com/gateway.do?";
        #endregion



        [Authorize]
        public ActionResult Payment()
        {
            var orderNumber = Request.QueryString["orderNumber"];
            var paymentType = Request.QueryString["paymentType"];
            var model = new PaymentModel();
            var order = model.GetOrderBasicInfoByOrderId(orderNumber);
            if (order == null)
            {
                return new EmptyResult();
            }
            Kevin.Comm.Logger.Tracer.TraceLog("Payment Pay:" + orderNumber, "orderPayment", "orderPayment", true);

            return Content(AliPay(order));
        }

        [ValidateInput(false)]
        public ActionResult PaymentCallback()
        {

            var sPara = GetRequestGet();
            Kevin.Comm.Logger.Tracer.TraceLog("Payment callback:" + sPara["traceInfo"], "orderPayment", "orderPayment", true);
            //商户订单号
            string order_no = Request.QueryString["out_trade_no"];

            //支付宝交易号
            string trade_no = Request.QueryString["trade_no"];

            //交易状态
            string result = Request.QueryString["is_success"];

            if (!string.IsNullOrEmpty(result) && result.ToLower() == "t")
            {
                ////修改订单状态&新建支付信息
                //PaymentModel model = new PaymentModel();
                //var order = model.GetOrderBasicInfoByOrderId(order_no);
                //var info = new OrderPaymentInfo
                //{
                //    OrderNumber = order_no,
                //    TradeNumber = trade_no,
                //    TransferAmount = order.OrderPayAmount,
                //    InDate = DateTime.Now,
                //    BuyerPaymentID = _seller_email,
                //    InUser = 100   //InUser还得考虑一下如何搞啊
                //};
                //var response = RestfulHelper.Update(SiteUrl.FormatUrl("SalesManagement_CreateOrderPaymentInfo"), info);

                ////For testing add comment
                //if (order.ProductList.Any(p => "10050001001  10040002001  10390002005  10390002006 10390002007  10390002008  10390002009  10390002010".Contains(p.ProductId)))
                //{
                //    return RedirectToAction("PublishComment", "MyAccount", new { prd = order.ProductList[0].ProductId, orderNumber = order.OrderNumber, ft = 1 });
                //}

                return RedirectToAction("PaymentCompleted", new { status = 1 });
            }
            else
            {
                return RedirectToAction("PaymentCompleted", new { status = 0 });
            }

        }

        [ValidateInput(false)]
        public ActionResult PaymentNotify()
        {
            string result = "fail";
            try
            {
                Dictionary<string, string> sPara = GetRequestPost();
                //Tracer.TraceLog("Payment Notify:" + sPara["traceInfo"], "orderPayment", "orderPayment", true);
                //Tracer.TraceLog("Payment Form:" + sPara.ToString(), "orderPayment", "orderPayment", true);




                if (sPara.Count > 0)//判断是否有带返回参数
                {

                    //获得签名结果
                    bool verifyResult = false;
                    var sParaTemp = Kevin.Shop.Integration.PaymentInterface.AlipayMobile.Core.FilterPara(sPara);
                    var stp = Kevin.Shop.Integration.PaymentInterface.AlipayMobile.Core.SortPara(sParaTemp);
                    var preSignStr = Kevin.Shop.Integration.PaymentInterface.AlipayMobile.Core.CreateLinkString(stp);

                    if (Request.Form["sign_type"] == "RSA")
                    {
                        verifyResult = RSAFromPkcs8.verify(preSignStr, Request.Form["sign"], _RSA_public_key, _input_charset);
                    }
                    else if (Request.Form["sign_type"] == "MD5")
                    {
                        verifyResult = AlipayMD5.Verify(preSignStr, Request.Form["sign"], _key, _input_charset);
                    }
                    if (verifyResult)
                    {
                        Tracer.TraceLog("签名验证成功", Request.Form["sign_type"], "orderPayment", false);
                        /////////////////////////////////////////////////////////////////////////////////////////////////////////////
                        //请在这里加上商户的业务逻辑程序代码
                        //——请根据您的业务逻辑来编写程序（以下代码仅作参考）——
                        //获取支付宝的通知返回参数，可参考技术文档中服务器异步通知参数列表

                        //解密（如果是RSA签名需要解密，如果是MD5签名则下面一行清注释掉）
                        //sPara = aliNotify.Decrypt(sPara);
                        //XML解析notify_data数据

                        string trade_no = Request.Form["trade_no"];              //支付宝交易号
                        string order_no = Request.Form["out_trade_no"];	        //获取订单号
                        string total_fee = Request.Form["total_fee"];            //获取总金额
                        string subject = Request.Form["subject"];                //商品名称、订单名称
                        string body = Request.Form["body"];                      //商品描述、订单备注、描述
                        string buyer_email = Request.Form["buyer_email"];        //买家支付宝账号
                        string trade_status = Request.Form["trade_status"];      //交易状态
                        decimal order_fee = 0;
                        Decimal.TryParse(total_fee, out order_fee);


                        //XmlDocument xmlDoc = new XmlDocument();
                        //xmlDoc.LoadXml(sPara["notify_data"]);
                        ////商户订单号
                        //string order_no = xmlDoc.SelectSingleNode("/notify/out_trade_no").InnerText;
                        ////支付宝交易号
                        //string trade_no = xmlDoc.SelectSingleNode("/notify/trade_no").InnerText;
                        ////交易状态
                        //trade_status = xmlDoc.SelectSingleNode("/notify/trade_status").InnerText;
                        ////交易金额
                        //string total_fee = xmlDoc.SelectSingleNode("/notify/price").InnerText;
                        ////交易金额
                        //string buyer_email = xmlDoc.SelectSingleNode("/notify/buyer_email").InnerText;
                        //decimal order_fee = 0;
                        Decimal.TryParse(total_fee, out order_fee);
                        if (trade_status == "WAIT_BUYER_PAY")
                        {
                            Tracer.TraceLog("Payment WAIT BUYER PAY:" + order_no + " WAIT BUYER PAY.", "orderPayment", "orderPayment", false);
                            result = "success";
                        }
                        else if (trade_status == "TRADE_FINISHED" || trade_status == "TRADE_SUCCESS" && !string.IsNullOrEmpty(order_no))
                        {
                            string orderNumberFlage = order_no;
                            if (order_no.Contains("_") && order_no.Split('_').Length == 2)
                            {
                                orderNumberFlage = order_no.Split('_')[0];
                            }

                            PaymentModel model = new PaymentModel();
                            var info = new OrderPaymentInfo
                                           {
                                               OrderNumber = orderNumberFlage,
                                               TradeNumber = trade_no,
                                               TransferAmount = order_fee,
                                               InDate = DateTime.Now,
                                               BuyerPaymentID = buyer_email,
                                               InUser = 100
                                           };
                            var response = RestfulHelper.Update(SiteUrl.FormatUrl("SalesManagement_CreateOrderPaymentInfo"), info);
                            Tracer.TraceLog("Payment Notify:" + orderNumberFlage + " Pay success.", "orderPayment", "orderPayment", false);
                            result = "success";  //请不要修改或删除

                        }
                        //if (trade_status == "TRADE_FINISHED")
                        //{
                        //    //判断该笔订单是否在商户网站中已经做过处理
                        //    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                        //    //如果有做过处理，不执行商户的业务程序

                            //    //注意：
                        //    //该种交易状态只在两种情况下出现
                        //    //1、开通了普通即时到账，买家付款成功后。
                        //    //2、开通了高级即时到账，从该笔交易成功时间算起，过了签约时的可退款时限（如：三个月以内可退款、一年以内可退款等）后。

                            //    //Response.Write("success");  //请不要修改或删除
                        //}
                        //else if (trade_status == "TRADE_SUCCESS")
                        //{
                        //    //判断该笔订单是否在商户网站中已经做过处理
                        //    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                        //    //如果有做过处理，不执行商户的业务程序
                        //    //注意：
                        //    //该种交易状态只在一种情况下出现——开通了高级即时到账，买家付款成功后。

                            //    //Response.Write("success");  //请不要修改或删除
                        //    //修改订单状态&新建支付信息

                            //}
                        else
                        {
                            result = trade_status;
                        }
                        Tracer.TraceLog("Payment Notify Payment:" + trade_status, string.Empty, "orderPayment", false);
                    }
                    else//验证失败
                    {
                        result = "fail";
                        Tracer.TraceLog("签名验证失败", string.Empty, "orderPayment", false);
                    }
                }
            }
            catch (Exception e)
            {
                Tracer.TraceLog("Payment Notify Payment Error:" + e, string.Empty, "orderPayment", false);
            }

            return Content(result);
        }
        /// <summary>
        /// 获取支付宝GET过来通知消息，并以“参数名=参数值”的形式组成数组
        /// </summary>
        /// <returns>request回来的信息组成的数组</returns>
        public Dictionary<string, string> GetRequestGet()
        {

            int i = 0;
            Dictionary<string, string> sArray = new Dictionary<string, string>();
            NameValueCollection coll;
            //Load Form variables into NameValueCollection variable.
            coll = Request.QueryString;

            // Get names of all forms into a string array.
            String[] requestItem = coll.AllKeys;
            var logInfo = new StringBuilder();
            for (i = 0; i < requestItem.Length; i++)
            {
                sArray.Add(requestItem[i], Request.QueryString[requestItem[i]]);
                logInfo.AppendLine("key:" + requestItem[i] + " vlaue:" + Request.QueryString[requestItem[i]]);
            }
            sArray.Add("traceInfo", logInfo.ToString());
            return sArray;
        }


        /// <summary>
        /// 获取支付宝POST过来通知消息，并以“参数名=参数值”的形式组成数组
        /// </summary>
        /// <returns>request回来的信息组成的数组</returns>
        public Dictionary<string, string> GetRequestPost()
        {
            int i = 0;
            Dictionary<string, string> sArray = new Dictionary<string, string>();
            NameValueCollection coll;
            //Load Form variables into NameValueCollection variable.
            coll = Request.Form;
            // Get names of all forms into a string array.
            String[] requestItem = coll.AllKeys;
            var logInfo = new StringBuilder();
            for (i = 0; i < requestItem.Length; i++)
            {
                sArray.Add(requestItem[i], Request.Form[requestItem[i]]);
                logInfo.AppendLine("key:" + requestItem[i] + " vlaue:" + Request.Form[requestItem[i]]);
            }

            Tracer.TraceLog("Payment Notify:/n" + logInfo.ToString(), "orderPayment", "orderPayment", true);
            //sArray.Add("traceInfo", logInfo.ToString());
            return sArray;
        }
        private string AliPay(OrderBasicInfo order)
        {
            ////////////////////////////////////////////请求参数////////////////////////////////////////////

            //必填参数//


            string subject = SiteSettings.DefaultSiteName + "_" + order.OrderNumber; //订单名称，显示在支付宝收银台里的“商品名称”里，显示在支付宝的交易管理的“商品名称”的列表里。
            string body = order.CustomerUserName + "_Order" + order.OrderNumber; //订单描述、订单详细、订单备注，显示在支付宝收银台里的“商品描述”里
            string price = order.OrderPayAmount.ToString(); //订单总金额，显示在支付宝收银台里的“商品单价”里

            string logistics_fee = "0.00"; //物流费用，即运费。
            string logistics_type = "EXPRESS"; //物流类型，三个值可选：EXPRESS（快递）、POST（平邮）、EMS（EMS）
            string logistics_payment = "BUYER_PAY"; //物流支付方式，两个值可选：SELLER_PAY（卖家承担运费）、BUYER_PAY（买家承担运费）

            string quantity = "1"; //商品数量，建议默认为1，不改变值，把一次交易看成是一次下订单而非购买一件商品。

            //选填参数//

            //买家收货信息（推荐作为必填）
            //该功能作用在于买家已经在商户网站的下单流程中填过一次收货信息，而不需要买家在支付宝的付款流程中再次填写收货信息。
            //若要使用该功能，请至少保证receive_name、receive_address有值
            //收货信息格式请严格按照姓名、地址、邮编、电话、手机的格式填写
            //string receive_name = "收货人姓名";			                    //收货人姓名，如：张三
            //string receive_address = "收货人地址";			                //收货人地址，如：XX省XXX市XXX区XXX路XXX小区XXX栋XXX单元XXX号
            //string receive_zip = "123456";                  			    //收货人邮编，如：123456
            //string receive_phone = "0571-81234567";                		    //收货人电话号码，如：0571-81234567
            //string receive_mobile = "13312341234";               		    //收货人手机号码，如：13312341234

            //网站商品的展示地址，不允许加?id=123这类自定义参数
            string show_url = "http://www.xxx.com/myorder.aspx";

            ////////////////////////////////////////////////////////////////////////////////////////////////

            //把请求参数打包成数组
            SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>();
            sParaTemp.Add("payment_type", "1");
            sParaTemp.Add("show_url", show_url);
            sParaTemp.Add("out_trade_no", order.OrderNumber);
            sParaTemp.Add("subject", subject);
            sParaTemp.Add("body", body);
            sParaTemp.Add("total_fee", order.OrderPayAmount.ToString());
            //sParaTemp.Add("paymethod", "bankPay");
            //sParaTemp.Add("defaultbank", "ICBC");
            sParaTemp.Add("extra_common_param", order.OrderType.ToString());
            //sParaTemp.Add("anti_phishing_key", anti_phishing_key);	//这个暂时还不知道怎么设置
            //sParaTemp.Add("exter_invoke_ip", exter_invoke_ip);
            //sParaTemp.Add("extra_common_param", extra_common_param);
            //sParaTemp.Add("buyer_email", buyer_email);
            //sParaTemp.Add("royalty_type", royalty_type);
            //sParaTemp.Add("royalty_parameters", royalty_parameters);

            //构造即时到帐接口表单提交HTML数据，无需修改
            string sHtmlText = Create_direct_pay_by_user(sParaTemp);
            return sHtmlText;
        }

        public string Create_direct_pay_by_user(SortedDictionary<string, string> sParaTemp)
        {
            //增加基本配置
            sParaTemp.Add("service", "create_direct_pay_by_user");
            sParaTemp.Add("partner", _partner);
            sParaTemp.Add("_input_charset", _input_charset);
            sParaTemp.Add("seller_email", _seller_email);
            sParaTemp.Add("return_url", _return_url);
            sParaTemp.Add("notify_url", _notify_url);

            //确认按钮显示文字
            string strButtonValue = "确认";
            //表单提交HTML数据
            string strHtml = "";

            //构造表单提交HTML数据
            strHtml = BuildFormHtml(sParaTemp, GATEWAY_NEW, "get", strButtonValue);

            return strHtml;
        }

        /// <summary>
        /// 除去数组中的空值和签名参数并以字母a到z的顺序排序
        /// </summary>
        /// <param name="dicArrayPre">过滤前的参数组</param>
        /// <returns>过滤后的参数组</returns>
        public static Dictionary<string, string> FilterPara(SortedDictionary<string, string> dicArrayPre)
        {
            Dictionary<string, string> dicArray = new Dictionary<string, string>();
            foreach (KeyValuePair<string, string> temp in dicArrayPre)
            {
                if (temp.Key.ToLower() != "sign" && temp.Key.ToLower() != "sign_type" && temp.Value != "" && temp.Value != null)
                {
                    dicArray.Add(temp.Key.ToLower(), temp.Value);
                }
            }

            return dicArray;
        }
        /// <summary>
        /// 生成要请求给支付宝的参数数组
        /// </summary>
        /// <param name="sParaTemp">请求前的参数数组</param>
        /// <returns>要请求的参数数组</returns>
        private Dictionary<string, string> BuildRequestPara(SortedDictionary<string, string> sParaTemp)
        {
            //待签名请求参数数组
            Dictionary<string, string> sPara = new Dictionary<string, string>();
            //签名结果
            string mysign = "";

            //过滤签名参数数组
            sPara = Kevin.Shop.Integration.ExpansionPlugin.PaymentInterface.AlipayDirect.Core.FilterPara(sParaTemp);

            //获得签名结果
            mysign = Kevin.Shop.Integration.ExpansionPlugin.PaymentInterface.AlipayDirect.Core.BuildMysign(sPara, _key, _sign_type, _input_charset);

            //签名结果与签名方式加入请求提交参数组中
            sPara.Add("sign", mysign);
            sPara.Add("sign_type", _sign_type);

            return sPara;
        }


        /// <summary>
        /// 构造提交表单HTML数据
        /// </summary>
        /// <param name="sParaTemp">请求参数数组</param>
        /// <param name="gateway">网关地址</param>
        /// <param name="strMethod">提交方式。两个值可选：post、get</param>
        /// <param name="strButtonValue">确认按钮显示文字</param>
        /// <returns>提交表单HTML文本</returns>
        public string BuildFormHtml(SortedDictionary<string, string> sParaTemp, string gateway, string strMethod, string strButtonValue)
        {
            //待请求参数数组
            Dictionary<string, string> dicPara = new Dictionary<string, string>();
            dicPara = BuildRequestPara(sParaTemp);

            StringBuilder sbHtml = new StringBuilder();

            sbHtml.Append("<form id='alipaysubmit' name='alipaysubmit' action='" + gateway + "_input_charset=" + _input_charset + "' method='" + strMethod.ToLower().Trim() + "'>");

            foreach (KeyValuePair<string, string> temp in dicPara)
            {
                sbHtml.Append("<input type='hidden' name='" + temp.Key + "' value='" + temp.Value + "'/>");
            }

            //submit按钮控件请不要含有name属性
            sbHtml.Append("<input type='submit' value='" + strButtonValue + "' style='display:none;'></form>");

            sbHtml.Append("<script>document.forms['alipaysubmit'].submit();</script>");

            return sbHtml.ToString();
        }

    }


}
